﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Simple.Repository.Models.Article;
using Simple.Services.System.Article.Model;
using Simple.Services.System.FileInfo;

namespace Simple.Services.System.Article
{
    public class ArticleService : BusinessBaseService
    {
        private readonly SimpleDbContext _context;
        private readonly CacheService _cacheService;
        private readonly FileInfoService _fileInfoService;
        private readonly ICurrentUserService _currentUser;

        public ArticleService(SimpleDbContext context,
                           ISimpleService services,
                           CacheService cacheService,
                           FileInfoService fileInfoService,
                           ICurrentUserService currentUser) : base(services)
        {
            _context = context;
            _cacheService = cacheService;
            _fileInfoService = fileInfoService;
            _currentUser = currentUser;
        }

        public async Task<ArticleCategoryOutPutModel> GetArticleCategoryAsync(Guid? categoryId)
        {
            if (!categoryId.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,文章分类Id参数不能为Null!");
            }

            var articleCategoryInfo = await _context.Set<ArticleCategory>().FirstOrDefaultAsync(c => c.Id == categoryId);

            if (articleCategoryInfo == null)
            {
                throw AppResultException.Status409Conflict("未找到文章分类相关数据!");
            }

            var outResult = MapperHelper.Map<ArticleCategoryOutPutModel>(articleCategoryInfo);
            return outResult;
        }

        public async Task<ArticleOutPutModel> GetArticleAsync(Guid? articleId)
        {
            if (!articleId.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,文章Id参数不能为Null!");
            }

            var articleInfo = await _context.Set<ArticleManage>().Include(c => c.ArticleCategory).Include(c => c.Images).FirstOrDefaultAsync(c => c.Id == articleId);

            if (articleInfo == null)
            {
                throw AppResultException.Status409Conflict("未找到相关文章数据!");
            }

            var outResult = MapperHelper.Map<ArticleOutPutModel>(articleInfo);
            return outResult;
        }


        public async Task<PageResultModel<ArticleCategoryOutPutModel>> GetArticleCategoryPageAsync(ArticleCategoryPageQueryModel input)
        {
            var result = new PageResultModel<ArticleCategoryOutPutModel>();
            var query = await OrganizationFilter(_context.Set<ArticleCategory>());

            if (!string.IsNullOrEmpty(input.CategoryName))
            {
                query = query.Where(m => EF.Functions.Like(m.CategoryName, $"%{input.CategoryName}%"));
            }

            if (input.IsShow.HasValue)
            {
                query = query.Where(m => m.IsShow == input.IsShow);
            }

            // 排序
            query = query.OrderBy(c => c.SortValue).ThenByDescending(m => m.CreatedTime);

            // 获取总数量
            result.TotalRows = await query.CountAsync();

            // 分页查询
            query = query.Page(input.PageNo, input.PageSize);
            var articleCategoryResultList = await query.ToListAsync();
            result.Rows = MapperHelper.Map<List<ArticleCategoryOutPutModel>>(articleCategoryResultList);
            result.SetPage(input);
            result.CountTotalPage();

            return result;
        }


        public async Task<PageResultModel<ArticleOutPutModel>> GetArticlePageAsync(ArticlePageQueryModel input)
        {
            var result = new PageResultModel<ArticleOutPutModel>();
            var query = await OrganizationFilter(_context.Set<ArticleManage>().Include(c => c.Images).Include(c => c.ArticleCategory));

            Expression<Func<ArticleManage, bool>>? multipleSampleCodeConditions = null;
            if (!string.IsNullOrWhiteSpace(input.ShowRange))
            {
                multipleSampleCodeConditions = input.ShowRange.Select(no => (Expression<Func<ArticleManage, bool>>)(x => EF.Functions.Like(x.ShowRange, $"%{no}%")))?.ConcatOr();
            }

            if (multipleSampleCodeConditions != null)
            {
                query = query.Where(multipleSampleCodeConditions);
            }

            if (!string.IsNullOrEmpty(input.Title))
            {
                query = query.Where(m => EF.Functions.Like(m.Title, $"%{input.Title}%"));
            }

            if (input.CategoryId.HasValue)
            {
                query = query.Where(m => m.CategoryId == input.CategoryId);
            }

            // 排序
            query = query.OrderByDescending(m => m.CreatedTime);

            // 获取总数量
            result.TotalRows = await query.CountAsync();

            // 分页查询
            query = query.Page(input.PageNo, input.PageSize);
            var articleOutResultList = await query.ToListAsync();
            result.Rows = MapperHelper.Map<List<ArticleOutPutModel>>(articleOutResultList);

            result.SetPage(input);
            result.CountTotalPage();

            return result;
        }


        public async Task<int> AddCategoryAsync(ArticleCategoryOutPutModel model)
        {
            if (model == null)
            {
                throw AppResultException.Status409Conflict("参数不能为Null!");
            }

            var articleCategoryInfo = MapperHelper.Map<ArticleCategory>(model);
            await _context.AddAsync(articleCategoryInfo);
            return await _context.SaveChangesAsync();
        }

        public async Task<int> AddArticleAsync(ArticleCreateOrUpdateModel model)
        {
            if (model == null)
            {
                throw AppResultException.Status409Conflict("参数不能为Null!");
            }

            var images = new List<ArticleManageImage>();
            if (model.ImageList != null && model.ImageList.Any())
            {
                foreach (var file in model.ImageList)
                {
                    var fileId = await _fileInfoService.UploadAsync(new FileInfo.Models.FileInfoInputModel { BusinessType = FileSource.Article, File = file });
                    images.Add(new ArticleManageImage { FiledId = fileId, FileName = file.FileName, FileSize = GetFileSize(file.Length) });
                }
            }

            if (model.CategoryId.HasValue)
            {
                var category = await GetArticleCategoryAsync(model.CategoryId);
                if (category == null)
                {
                    throw AppResultException.Status409Conflict("找不到文章分类数据!");
                }
            }

            var articleManageInfo = MapperHelper.Map<ArticleManage>(model);
            articleManageInfo.Images = images;
            await _context.AddAsync(articleManageInfo);
            return await _context.SaveChangesAsync();
        }
        private string GetFileSize(long size)
        {
            var num = 1024.00;
            if (size < num)
                return size + " B";
            if (size < Math.Pow(num, 2))
                return (size / num).ToString("f2") + " KB";
            if (size < Math.Pow(num, 3))
                return (size / Math.Pow(num, 2)).ToString("f2") + " MB";
            if (size < Math.Pow(num, 4))
                return (size / Math.Pow(num, 3)).ToString("f2") + " GB";
            return (size / Math.Pow(num, 4)).ToString("f2") + " TB";
        }

        public async Task<int> UpdateCategoryAsync(ArticleCategoryOutPutModel model)
        {
            if (!model.Id.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,文章分类Id参数不能为Null!");
            }

            var categoryInfos = _context.Set<ArticleCategory>().Where(m => model.Id == m.Id || m.CategoryName == model.CategoryName)?.ToList();
            var _categoryInfo = categoryInfos?.FirstOrDefault(c => c.CategoryName == model.CategoryName);
            if (_categoryInfo != null && _categoryInfo.Id != model.Id)
            {
                throw AppResultException.Status409Conflict("分类名称已存在，更新失败！");
            }

            var categoryInfo = categoryInfos?.FirstOrDefault(c => c.Id == model.Id);
            if (categoryInfo == null)
            {
                throw AppResultException.Status404NotFound("未找到分类相关数据，更新失败！");
            }
            
            categoryInfo.SortValue = model.SortValue;
            categoryInfo.CategoryName = model.CategoryName;
            categoryInfo.IsShow = model.IsShow;
            categoryInfo.Remark = model.Remark;
            _context.Update(categoryInfo);
            int ret = await _context.SaveChangesAsync();

            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        public async Task<int> UpdateArticleAsync(ArticleCreateOrUpdateModel model)
        {
            if (!model.Id.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,文章Id参数不能为Null!");
            }

            var articleInfo = await _context.Set<ArticleManage>().Include(c => c.Images)
                .Where(m => model.Id == m.Id)
                .FirstOrDefaultAsync();

            if (articleInfo == null)
            {
                throw AppResultException.Status404NotFound("未找到文章相关数据，更新失败！");
            }

            if (model.CategoryId.HasValue)
            {
                var category = await GetArticleCategoryAsync(model.CategoryId);
                if (category == null)
                {
                    throw AppResultException.Status409Conflict("找不到文章分类数据!");
                }
            }

            if (articleInfo?.Images != null && articleInfo.Images.Any())
            {
                _context.RemoveRange(articleInfo.Images);
            }

            var images = new List<ArticleManageImage>();
            if (model.ImageList != null && model.ImageList.Any())
            {
                foreach (var file in model.ImageList)
                {
                    var fileId = await _fileInfoService.UploadAsync(new FileInfo.Models.FileInfoInputModel { BusinessType = FileSource.ClassDynamics, File = file });
                    images.Add(new ArticleManageImage { FiledId = fileId, FileName = file.FileName, FileSize = GetFileSize(file.Length) });
                }

                if (images != null && images.Any())
                {
                    articleInfo.Images = images;
                }
            }

            articleInfo.ArticleContent = model.ArticleContent;
            articleInfo.CategoryId = model.CategoryId;
            articleInfo.Title = model.Title;
            articleInfo.IsShow = model.IsShow;
            articleInfo.ShowRange = model.ShowRange;
            _context.Update(articleInfo);
            int ret = await _context.SaveChangesAsync();

            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        public async Task<int> DeleteCategoryAsync(List<Guid?> ids)
        {
            if (ids == null || !ids.Any())
            {
                throw AppResultException.Status409Conflict("参数错误,文章分类Id参数不能为Null!");
            }

            var categoryOutResultList = await _context.Set<ArticleCategory>().Include(c => c.ArticleManages)
                .Where(m => ids.Contains(m.Id))
                .ToListAsync();

            if (categoryOutResultList == null || !categoryOutResultList.Any())
            {
                throw AppResultException.Status404NotFound("未找到文章分类相关数据，删除失败！");
            }

            var articleList = categoryOutResultList?.SelectMany(c => c.ArticleManages)?.ToList();
            if (articleList != null && articleList.Any())
            {
                throw AppResultException.Status404NotFound("删除失败，系统检测到某些分类下存在文章相关数据！请先删除文章后再试！");
            }

            // 先更新数据库
            _context.RemoveRange(categoryOutResultList);
            int ret = await _context.SaveChangesAsync();
            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        public async Task<int> DeleteArticleAsync(List<Guid?> ids)
        {
            if (ids == null || !ids.Any())
            {
                throw AppResultException.Status409Conflict("参数错误,班级动态Id参数不能为Null!");
            }

            var articleOutResultList = await _context.Set<ArticleManage>().Include(c => c.Images)
                .Where(m => ids.Contains(m.Id))
                .ToListAsync();

            if (articleOutResultList == null || !articleOutResultList.Any())
            {
                throw AppResultException.Status404NotFound("未找到文章相关数据，删除失败！");
            }

            // 先更新数据库
            _context.RemoveRange(articleOutResultList);
            int ret = await _context.SaveChangesAsync();
            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        public async Task<List<ArticleCategoryOutPutModel>> GetCategorAll()
        {
            var query = await OrganizationFilter(_context.Set<ArticleCategory>().Include(c => c.ArticleManages));
            var result = await query.ToListAsync();
            if (result == null || !result.Any())
            {
                return new List<ArticleCategoryOutPutModel>();
            }

            return MapperHelper.Map<List<ArticleCategoryOutPutModel>>(result) ?? new List<ArticleCategoryOutPutModel>();
        }

        public async Task<ArticleOutPutModel> Read(Guid? Id)
        {
            if (!Id.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,文章Id参数不能为Null!");
            }

            var article = await _context.Set<ArticleManage>().Include(c => c.Images).Include(c => c.ArticleCategory).FirstOrDefaultAsync(c => c.Id == Id);
            if (article == null)
            {
                throw AppResultException.Status409Conflict("找不到文章相关数据!");
            }

            article.ReadCount++;
            _context.Update(article);
            await _context.SaveChangesAsync();
            return MapperHelper.Map<ArticleOutPutModel>(article);
        }
    }
}
